﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Mapping;
using NHibernate.SqlCommand;
using OurSite.Business.Picture;
using OurSite.Business.Video;

namespace OurSite.Business.Repositories
{
    public class VideoRepository : BaseRepository, IVideoRepository
    {
        public void Add(Video.Video video)
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.Save(video);
                transaction.Commit();
            }
        }

        public void Update(Video.Video video)
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.Update(video);
                transaction.Commit();
            }
        }

        public void Remove(Video.Video video)
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.Delete(video);
                transaction.Commit();
            }
        }
               
        public Video.Video GetById(Guid videoId)
        {
            using (var tx = session.BeginTransaction())
            {
                var video = session.Get<Video.Video>(videoId);
                tx.Commit();
                return video;
            }
        }

        public Video.Video GetListingVideoByEventID(Guid eventId)
        {
            using (var tx = session.BeginTransaction())
            {
                Video.Video video = session
                    .CreateCriteria<Video.Video>()
                    .Add(Restrictions.Eq("EventId", eventId))
                    .UniqueResult<Video.Video>();
                tx.Commit();
                return video;
            }
        }

        public Video.Video GetBlankVideo()
        {
            Video.Video video = new Video.Video { URL = "" };
            return video;
        }
        
        public IList<Video.Video> GetByEventID(Guid eventId)
        {
            using (var tx = session.BeginTransaction())
            {
                var videos = session
                    .CreateCriteria<Picture.Picture>()
                    .Add(Restrictions.Eq("EventId", eventId))
                    .AddOrder(Order.Asc("Order"))
                    .List<Video.Video>();

                tx.Commit();
                return videos;
            }
        }
        
        public IList<Video.Video> GetAllVideos()
        {
            using (var tx = session.BeginTransaction())
            {
                var videos = session
                    .CreateCriteria<Video.Video>()
                    .AddOrder(Order.Asc("Order"))
                    .List<Video.Video>();

                tx.Commit();
                return videos;
            }
        }
        
        public IList<Video.Video> GetAllFavoriteVideos()
        {
            using (var tx = session.BeginTransaction())
            {
                var videos = session
                    .CreateCriteria<Video.Video>()
                    .Add(Restrictions.Eq("IsFavorite", true))
                    .List<Video.Video>();

                tx.Commit();
                return videos;
            }
        }

        public IList<Video.Video> GetTopFavoriteVideos(int numberToReturn)
        {
            using (var tx = session.BeginTransaction())
            {
                var videos = session
                    .CreateCriteria<Video.Video>()
                    .Add(Restrictions.Eq("IsFavorite", true))
                    .SetMaxResults(numberToReturn)
                    .AddOrder(new RandomOrder())
                    .List<Video.Video>();

                tx.Commit();
                return videos;
            }
        }

        public int GetNextVideoCode()
        {
            using (var tx = session.BeginTransaction())
            {
                int videoCode = session
                    .CreateCriteria<Video.Video>()
                    .SetProjection(
                    Projections.Max(
                        Projections.Cast(NHibernateUtil.Int32, Projections.Property("VideoCode"))
                        )
                    )
                    .UniqueResult<int>();

                tx.Commit();
                return videoCode + 1;
            }
        }

        public int GetNextOrderByEventID(Guid eventId)
        {
            using (var tx = session.BeginTransaction())
            {
                int order = session
                    .CreateCriteria<Video.Video>()
                    .Add(Restrictions.Eq("EventId", eventId))
                    .SetProjection(
                    Projections.Max(
                        Projections.Cast(NHibernateUtil.Int32, Projections.Property("Order"))
                        )
                    )
                    .UniqueResult<int>();

                tx.Commit();
                return order + 1;
            }
        }
    }
}
